/*
 * Copyright (c) 2001-2020 GuaHao.com Corporation Limited. All rights reserved.
 * This software is the confidential and proprietary information of GuaHao Company.
 * ("Confidential Information").
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the license agreement you entered into with GuaHao.com.
 */
package com.test;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.comments.Comment;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.type.Type;

import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.Optional;

/**
 * 说明：
 * 生成MarkDown文档
 *
 * @author baigt
 * @version V1.0
 * @since 2020-09-28 18:58
 */
public class JavaCodeComments {
       public static String basePath = "C:\\Users\\Administrator\\IdeaProjects\\psp-portal-service\\psp-portal-service-share\\src\\main\\java\\com\\guahao\\psp\\portal\\share\\prescription\\";
    public static ExcelWriter excelWriter = EasyExcel.write(new File("接口文档"+System.currentTimeMillis()+".xlsx"), JavaInterfaceDoc.class).build();;
    public static WriteSheet writeSheet = EasyExcel.writerSheet("接口文档").build();
    public static void main(String[] args) {
        try {
            generatePomAndInterfaceAndMethod("1.1.82", "com.guahao.psp.portal.share.prescription.ExternalPrescriptionExchangeService", "查询处方接口", "queryExternalPrescriptionDetail");
            System.out.println("\n\n\n");
            System.out.println("---");
            System.out.println("## 请求输入参数");
            System.out.println("### ExternalPscQueryParam");
            generateApi(basePath + "param\\ExternalPscQueryParam.java",1,"param");
            System.out.println("\n\n\n");
            System.out.println("---");
            System.out.println("## 响应输出参数");
            generateResult("Result<ExternalPrescriptionDetailResultDTO>");
            generateApi(basePath + "dto\\ExternalPrescriptionDetailResultDTO.java",1,"dto");
//            generatePage("List<PscTemplateListBO>");
        }finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }
    public static void main11(String[] args) {
        try {
            generatePomAndInterfaceAndMethod("1.1.82", "com.guahao.psp.portal.share.prescription.ExternalPrescriptionExchangeService", "创建中药处方接口", "createTcmPrescription");
            System.out.println("\n\n\n");
            System.out.println("---");
            System.out.println("## 请求输入参数");
            System.out.println("### ExternalCreateTcmParam");
            generateApi(basePath + "param\\ExternalCreateTcmParam.java",1,"param");
            System.out.println("\n\n\n");
            System.out.println("---");
            System.out.println("## 响应输出参数");
            generateResult("Result<PrescriptionCreateResultDTO>");
            generateApi(basePath + "dto\\PrescriptionCreateResultDTO.java",1,"dto");
//            generatePage("List<PscTemplateListBO>");
        }finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }


    public static void generateApi(String fileName,int size,String prefixSub) {
        try {
            CompilationUnit cu = JavaParser.parse(new FileInputStream(new File(fileName)));
            TypeDeclaration typeDeclaration = cu.getTypes().get(0);
            NodeList members = typeDeclaration.getMembers();
            System.out.println("|字段名|类型|说明|");
            System.out.println(
                    "|------------------------------------|------------------------------------|------------------------------------|");
            for(Object node:members){
                if (node instanceof FieldDeclaration) {
                    FieldDeclaration fieldDeclaration = (FieldDeclaration) node;
                    VariableDeclarator variableDeclarator = fieldDeclaration.getVariables().get(0);
                    String filedName = variableDeclarator.getName().getIdentifier();

                    if (!filedName.equals("serialVersionUID")) {
                        Type type = variableDeclarator.getType();
                        String fieldTypeName = type.toString();
                        Optional<Comment> comment = fieldDeclaration.getComment();
                        String fieldComment = !comment.isPresent() ? "" : comment.get().getContent().replaceAll("\r", "").replaceAll("\n", "").replaceAll("\t", "").replaceAll(" ", "").replaceAll("\\*","");
                        System.out.println("|" + filedName + "|" + fieldTypeName + "|" + fieldComment + "|");
                        String biTian="否";
                        for (AnnotationExpr annotation : fieldDeclaration.getAnnotations()) {
                            if (annotation.getName().toString().contains("Not")) {
                                biTian="是";
                            }
                        }
                        excelWriter.write(Arrays.asList(new JavaInterfaceDoc(setPlaceHolder(size)+filedName,fieldTypeName,biTian,fieldComment)),writeSheet);
                        System.out.println("name:"+type.getChildNodes());
                        if (type.getChildNodes().get(0).toString().equals("List")) {
                            String listType = type.getChildNodes().get(1).toString();
                            if (isObject(listType)) {
                                generateApi(basePath + prefixSub+"\\"+listType+".java",size+1,prefixSub);
                            }
                        }else if (isObject(fieldTypeName)) {
                            generateApi(basePath + prefixSub+"\\"+fieldTypeName+".java",size+1,prefixSub);
                        }

                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static String setPlaceHolder(int size){
        StringBuffer sb=new StringBuffer();
        if (size>1) {
            for (int i = 0; i < size; i++) {
                sb.append("- ");
            }
        }
        return sb.toString();
    }

    public static boolean isObject(String fieldTypeName) {
        if (fieldTypeName.equals("Integer")||fieldTypeName.equals("int")||fieldTypeName.equals("Double")||fieldTypeName.equals("double")||fieldTypeName.equals("String")||fieldTypeName.equals("Long")||fieldTypeName.equals("long")||fieldTypeName.equals("boolean")||fieldTypeName.equals("Boolean")||fieldTypeName.equals("Float")||fieldTypeName.equals("float")) {
            return false;
        }
        return true;
    }
    public static void generatePomAndInterfaceAndMethod(String version, String service, String methodTitle, String method) {
        System.out.println("## Maven依赖");
        StringBuffer sb = new StringBuffer();
        sb.append("```\n");
        String pom = "<dependency>\n" +
                "    <groupId>com.guahao.med</groupId>\n" +
                "    <artifactId>prescription-service-share</artifactId>\n" +
                "    <version>" + version + "-SNAPSHOT</version>\n" +
                "</dependency>";
        sb.append(pom);
        sb.append("\n```");
        System.out.println(sb.toString());
        System.out.println("## 接口名");
        System.out.println("> "+service);
        System.out.println("\n---");
        System.out.println("## " + methodTitle + "");
        System.out.println("> " + method + "");

    }

    /**
     * 基本Result
     *
     * @param returnObject
     */
    public static void generateResult(String returnObject) {
        System.out.println("### 响应输出参数：Result");
        System.out.println("|字段名|类型|说明|");
        System.out.println(
                "|------------------------------------|------------------------------------|------------------------------------|");
        System.out.println("|code|String|0成功，其他失败|");
        System.out.println("|message|String|返回消息|");
        System.out.println("|data|" + returnObject + "|返回结果对象|");
        excelWriter.write(Arrays.asList(new JavaInterfaceDoc("code","String","--","0成功，其他失败")),writeSheet);
        excelWriter.write(Arrays.asList(new JavaInterfaceDoc("message","String","--","返回消息")),writeSheet);
        excelWriter.write(Arrays.asList(new JavaInterfaceDoc("data",returnObject,"--","返回结果对象")),writeSheet);
    }

    /**
     * 基本Page
     *
     * @param returnObject
     */
    public static void generatePage(String returnObject) {
        System.out.println("### 响应输出参数：Page");

        System.out.println("|字段名|类型|说明|");
        System.out.println(
                "|------------------------------------|------------------------------------|------------------------------------|");
        System.out.println("|pageNumber|int|第几页|");
        System.out.println("|pageSize|int|每页条数|");
        System.out.println("|totalPages|int|总页数|");
        System.out.println("|totalCount|long|总条数|");
        System.out.println("|results|" + returnObject + "|返回结果对象|");
    }
}


@ContentRowHeight(15)
@HeadFontStyle(fontHeightInPoints = 11)
@ColumnWidth(25)
class JavaInterfaceDoc {
    /**
     * 参数名称
     */
    @ExcelProperty(value = "参数名称")
    private String argName;
    /**
     * 参数类型
     */
    @ExcelProperty("参数类型")
    private String argType;
    /**
     * 是否必填
     */
    @ExcelProperty(value = "是否必填")
    private String biTian;
    /**
     * 备注
     */
    @ExcelProperty(value = "备注")
    @ColumnWidth(80)
    private String desc;

    public JavaInterfaceDoc(String argName, String argType, String biTian, String desc) {
        this.argName = argName;
        this.argType = argType;
        this.biTian = biTian;
        this.desc = desc;
    }

    public String getArgName() {
        return argName;
    }

    public void setArgName(String argName) {
        this.argName = argName;
    }

    public String getArgType() {
        return argType;
    }

    public void setArgType(String argType) {
        this.argType = argType;
    }

    public String getBiTian() {
        return biTian;
    }

    public void setBiTian(String biTian) {
        this.biTian = biTian;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}
